package com.opdar.athena.support.service;

import com.alibaba.fastjson.JSON;
import com.alibaba.fastjson.JSONArray;
import com.alibaba.fastjson.JSONObject;
import com.opdar.athena.support.base.Constants;
import com.opdar.athena.support.base.ICacheManager;
import com.opdar.athena.support.entities.*;
import com.opdar.athena.support.mapper.*;
import com.opdar.athena.support.utils.MessageUtils;
import com.opdar.platform.utils.SHA1;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;
import org.springframework.util.StringUtils;

import java.math.BigDecimal;
import java.sql.Timestamp;
import java.util.*;

/**
 * Created by shiju on 2017/7/11.
 */
@Service
public class SupportUserService {
    @Autowired
    private SupportUserMapper supportUserMapper;
    @Autowired
    private UserMapper userMapper;
    @Autowired
    private ConversationMapper conversationMapper;
    @Autowired
    private AppMapper appMapper;
    @Autowired
    private SupportConfigMapper supportConfigMapper;
    @Autowired
    private GroupSupportMapper groupSupportMapper;
    @Autowired
    private MessageUtils messageUtils;
    @Autowired
    private ICacheManager<String, String, Object> cacheManager;

    public boolean init(String appId) {
        //初始化
        //查询所有权重值
        List<SupportUserEntity> list = findAllSupport(appId);
        if (list == null || list.size() == 0) return false;
        int countWeight = 0;
        for (SupportUserEntity supportUserEntity : list) {
            countWeight += supportUserEntity.getWeight();
        }
        List<WeightEntity> weights = new LinkedList<WeightEntity>();
        int start = 0;
        for (int i = 0; i < list.size(); i++) {
            SupportUserEntity supportUserEntity = list.get(i);
            if (supportUserEntity.getWeight() <= 0) continue;

            BigDecimal bigDecimal = null;
            if (list.size() - 1 == i) {
                bigDecimal = new BigDecimal(100 - start);
            } else {
                bigDecimal = new BigDecimal(supportUserEntity.getWeight()).divide(new BigDecimal(countWeight), 2, BigDecimal.ROUND_HALF_UP).multiply(new BigDecimal(100));
            }
            //计算出所占比
            WeightEntity weightEntity = new WeightEntity(start, (start += bigDecimal.intValue()));
            supportUserEntity.setUserPwd(null);
            supportUserEntity.setMessagePwd(null);
            supportUserEntity.setSalt(null);
            weightEntity.setSupport(supportUserEntity);
            weights.add(weightEntity);
        }
        cacheManager.set(appId, weights);
        return true;
    }

    public boolean canBefind(String supportId) {
        Integer userState = (Integer) cacheManager.hget(Constants.USER_STATE, supportId);
        if (userState == null) userState = 0;
        if (userState == 0 || userState == 1) {
            //可分配
            if (inWorktime(supportId)) return true;
        }
        return false;
    }

    private boolean inWorktime(String supportId) {
        SupportConfigEntity config = new SupportConfigEntity();
        config.setSupportId(supportId);
        config.setName(Constants.WORKTIME);
        config = supportConfigMapper.selectOne(config);
        if (config == null || config.getStat() == 0) return true;
        else {
            JSONArray array = JSON.parseArray(config.getConfig());
            Calendar calendar = Calendar.getInstance();
            int currentTime = calendar.get(Calendar.HOUR_OF_DAY) * 60 + calendar.get(Calendar.MINUTE);
            int dayOfWeek = 1 << (calendar.get(Calendar.DAY_OF_WEEK) - 1);
            for (int i = 0; i < array.size(); i++) {
                JSONObject object = array.getJSONObject(i);
                int start = object.getIntValue("start");
                int end = object.getIntValue("end");
                int weekday = object.getIntValue("weekday");
                if ((weekday & dayOfWeek) != 0 && start <= currentTime && end >= currentTime) {
                    return true;
                }
            }
        }
        return false;
    }

    public ConversationEntity getSupport(String userId, String utmSource, Integer reload, String appId, List<WeightEntity> weights) {
        try {
            UserEntity userEntity = new UserEntity();
            userEntity.setId(userId);
            userEntity = userMapper.selectOne(userEntity);
            //创建会话
            ConversationEntity conversationEntity = new ConversationEntity();
            conversationEntity.setUserId(userEntity.getId());
            conversationEntity.setAppId(appId);
            ConversationEntity _conversationEntity = conversationMapper.selectOne(conversationEntity);
            if (reload == null || reload == 0) {
                if (_conversationEntity != null && _conversationEntity.getSupportUserEntity() != null && canBefind(_conversationEntity.getSupportUserEntity().getId()))
                    return _conversationEntity;
            }
            int index = -1;
            int randomId = -1;
            WeightEntity weight = null;

            if (weights.size() > 1) {
                //刪除所有不能被尋找的用戶
                for (int i = 0; i < weights.size(); i++) {
                    WeightEntity _weight = weights.get(i);
                    if (!canBefind(_weight.getSupport().getId())) {
                        weights.remove(i);
                    }
                }
            }

            if (weights.size() > 1) {
                if (_conversationEntity != null) {
                    WeightEntity weightEntity = new WeightEntity();
                    weightEntity.setSupport(_conversationEntity.getSupportUserEntity());
                    index = weights.indexOf(weightEntity);
                    weights.remove(index);
                }
                int count = 100;
                while (count-- > 0) {
                    randomId = new Random().nextInt(100);
                    WeightEntity weightEntity = new WeightEntity(randomId);
                    index = weights.indexOf(weightEntity);
                    if (index >= 0) {
                        weight = weights.get(index);
                        break;
                    }
                }
            }

            if (weights.size() == 1) {
                weight = weights.get(0);
            }

            SupportUserEntity supportUserEntity = weight.getSupport();
            if (weights.size() == 1) {
                conversationEntity.setSupportId(supportUserEntity.getId());
                conversationEntity.setAppId(appId);
                if (conversationMapper.count(conversationEntity) == 0) {
                    conversationEntity.setId(UUID.randomUUID().toString());
                    conversationEntity.setStat(0);
                    conversationEntity.setSupportId(supportUserEntity.getId());
                    conversationEntity.setUserId(userEntity.getId());
                    conversationEntity.setAppId(appId);
                    conversationEntity.setUtmSource(utmSource);
                    conversationEntity.setCreateTime(new Timestamp(System.currentTimeMillis()));
                    conversationEntity.setUpdateTime(new Timestamp(System.currentTimeMillis()));
                    if (_conversationEntity != null) {
                        ConversationEntity where = new ConversationEntity();
                        where.setUserId(userEntity.getId());
                        where.setSupportId(_conversationEntity.getSupportUserEntity().getId());
                        where.setAppId(appId);
                        ConversationEntity update = new ConversationEntity();
                        update.setStat(2);
                        update.setEndTime(new Timestamp(System.currentTimeMillis()));
                        conversationMapper.update(update, where);
                    }
                    try {
                        SupportConfigEntity config = new SupportConfigEntity();
                        config.setName(Constants.AUTO_ADMIT);
                        config.setSupportId(supportUserEntity.getId());
                        config = supportConfigMapper.selectOne(config);
                        if (config.getStat() == 1 && !StringUtils.isEmpty(config.getConfig())) {
                            Integer status = Integer.valueOf(config.getConfig());
                            if (status != null) {
                                Integer userState = (Integer) cacheManager.hget(Constants.USER_STATE, conversationEntity.getSupportId());
                                if (userState != 3) {
                                    if ((status == Constants.AutoAdmitType.EVERYTIME) ||
                                            (status == Constants.AutoAdmitType.WORKTIME && inWorktime(conversationEntity.getSupportId())) ||
                                            (status == Constants.AutoAdmitType.ONLINE && userState == 0) ||
                                            (status == Constants.AutoAdmitType.LEAVING && userState == 1)
                                            ) {
                                        conversationEntity.setStartTime(new Timestamp(System.currentTimeMillis()));
                                        conversationEntity.setStat(1);
                                    }
                                }
                            }
                        }
                    } catch (Exception e) {
                        e.printStackTrace();
                    }
                    conversationMapper.insert(conversationEntity);
                }
                conversationEntity.setUserEntity(userEntity);
                conversationEntity.setSupportUserEntity(supportUserEntity);
                return conversationEntity;
            } else {
                weights.remove(index);
                return getSupport(userId, utmSource, 1, appId, weights);
            }
        } catch (Exception e) {
            e.printStackTrace();
        }
        return null;
    }

    public List<SupportUserEntity> findAllSupport(String appId) {
        SupportUserEntity support = new SupportUserEntity();
        support.setAppId(appId);
        return supportUserMapper.selectList(support);
    }


    public List<SupportUserEntity> findAllSupport(String groupId, String appId) {
        return supportUserMapper.selectByGroup(groupId, appId);
    }

    @Transactional(rollbackFor = Throwable.class)
    public SupportUserEntity regist(String userName, String userPwd) {
        AppEntity appEntity = new AppEntity();
        appEntity.setId(UUID.randomUUID().toString().replace("-", ""));
        appEntity.setCreateTime(new Timestamp(System.currentTimeMillis()));
        appEntity.setUpdateTime(new Timestamp(System.currentTimeMillis()));
        SupportUserEntity supportUserEntity = regist(userName, userPwd, null, null, 100, "ADMIN", appEntity.getId());
        if (supportUserEntity != null) {
            appMapper.insert(appEntity);
            return supportUserEntity;
        }
        return null;
    }

    @Transactional(rollbackFor = Throwable.class)
    public SupportUserEntity registToGroup(String groupId, String userName, String userPwd, String nickName, Integer weight, String avatar, String role, String appId) {
        SupportUserEntity supportUserEntity = regist(userName, userPwd, avatar, nickName, weight, role, appId);
        GroupSupportEntity groupSupportEntity = new GroupSupportEntity();
        groupSupportEntity.setId(UUID.randomUUID().toString());
        groupSupportEntity.setGroupId(groupId);
        groupSupportEntity.setSupportId(supportUserEntity.getId());
        groupSupportEntity.setCreateTime(new Timestamp(System.currentTimeMillis()));
        groupSupportEntity.setUpdateTime(new Timestamp(System.currentTimeMillis()));
        groupSupportMapper.insert(groupSupportEntity);
        return supportUserEntity;
    }

    @Transactional(rollbackFor = Throwable.class)
    public boolean updateToGroup(String id, String userName, String userPwd, String nickName, Integer weight, String avatar) {
        SupportUserEntity update = new SupportUserEntity();
        update.setUserName(userName);
        if(!StringUtils.isEmpty(userPwd)){
            String salt = UUID.randomUUID().toString();
            userPwd = SHA1.encrypt(userPwd + salt);
            update.setSalt(salt);
            update.setUserPwd(userPwd);
        }
        update.setNickName(nickName);
        update.setWeight(weight);
        update.setAvatar(avatar);
        SupportUserEntity where = new SupportUserEntity();
        where.setId(id);
        supportUserMapper.update(update,where);
        return true;
    }

    @Transactional(rollbackFor = Throwable.class)
    public SupportUserEntity regist(String userName, String userPwd, String avatar, String nickName, Integer weight, String role, String appId) {
        SupportUserEntity user = new SupportUserEntity();
        user.setUserName(userName);
        if (supportUserMapper.count(user) == 0) {
            user.setId(UUID.randomUUID().toString());
            String salt = UUID.randomUUID().toString();
            userPwd = SHA1.encrypt(userPwd + salt);
            user.setUserPwd(userPwd);
            user.setSalt(salt);
            if (nickName == null) nickName = userName;
            user.setNickName(nickName);
            if (weight == null) weight = 0;
            user.setWeight(weight);
            user.setRole(role);
            user.setAvatar(avatar);
            user.setAppId(appId);
            user.setMessagePwd(UUID.randomUUID().toString());
            JSONObject object = messageUtils.regist(user.getId(), user.getMessagePwd());
            if (object != null) {
                user.setMessageId(object.getString("id"));
            }
            user.setCreateTime(new Timestamp(System.currentTimeMillis()));
            user.setUpdateTime(new Timestamp(System.currentTimeMillis()));
            if (supportUserMapper.insert(user) > 0) {
                init(appId);
                return user;
            }
        }
        return null;
    }

    public SupportUserEntity login(String userName, String userPwd) {
        SupportUserEntity user = new SupportUserEntity();
        user.setUserName(userName);
        user = supportUserMapper.selectOne(user);
        userPwd = SHA1.encrypt(userPwd + user.getSalt());
        if (user.getUserPwd().equals(userPwd)) {
            user.setUserPwd(null);
            user.setSalt(null);
            return user;
        }
        return null;
    }
}
